﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Naruto.Subscribe.Attributes;
using Naruto.Subscribe.Extension;
using Naruto.Subscribe.Interface;
using Naruto.Subscribe.Object;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace Naruto.Subscribe.Internal
{
    /// <summary>
    /// 
    /// </summary>
    internal class SubscribeHandler : ISubscribeHandler
    {
        private readonly ILogger logger;
        private readonly IMethodCache methodCache;

        public SubscribeHandler(ILogger<SubscribeHandler> _logger, IMethodCache _methodCache)
        {
            logger = _logger;
            methodCache = _methodCache;
        }
        /// <summary>
        /// 开始处理订阅所对应的方法
        /// </summary>
        /// <param name="subscribeName">订阅名称</param>
        /// <param name="messageModel">消息模型</param>
        /// <returns></returns>
        public async Task HandlerAsync(string subscribeName, MessageModel messageModel, IServiceProvider serviceProvider)
        {
            subscribeName.CheckNullOrEmpty();
            //验证消息信息
            if (messageModel == null)
            {
                return;
            }

            logger.LogTrace("开始处理接收到的订阅信息,subscribeName:{subscribeName},MessageContent:{MessageContent}", subscribeName, messageModel.MessageContent);
            //查找当前订阅信息对应的 所处的对象信息
            var baseSubscribeType = SubscribeTypeFactory.Get(subscribeName);
            if (baseSubscribeType == null)
            {
                logger.LogWarning("查找不到指定的订阅信息:channel:{channel}", subscribeName);
                return;
            }

            //根据类型获取泛型
            var dynamicMethod = serviceProvider.GetRequiredService(typeof(DynamicMethodExpression<>).MakeGenericType(baseSubscribeType.ServiceType)) as IDynamicMethodExpression;

            //获取当前执行方法的参数
            var methodCacheModel = methodCache.Get(baseSubscribeType);

            if (methodCacheModel == null)
            {
                return;
            }
            //参数实体集合
            var parameterEntityList = BuildParameter(methodCacheModel.Parameters, messageModel);
            //获取拦截器
            var messageIntercept = serviceProvider.GetService<IMessageIntercept>();
            if (messageIntercept != null)
            {
                await messageIntercept.ExecuteingAsync(new NarutoMessageEventData
                {
                    ServiceProvider = serviceProvider,
                    Message = messageModel
                });
            }

            //获取对象的实例
            var instance = GetObjInstance(serviceProvider, baseSubscribeType);
            //操作动态执行方法接口
            await dynamicMethod.ExecAsync(service: instance, action: baseSubscribeType.MethodName, methodCacheModel.IsAsync, parameterEntityList);

            //消息处理后的aop事件
            if (messageIntercept != null)
            {
                await messageIntercept.ExecutedAsync(new NarutoMessageEventData
                {
                    ServiceProvider = serviceProvider,
                    Message = messageModel
                });
            }
            logger.LogTrace("处理完毕接受到的订阅信息");
        }
        /// <summary>
        /// 获取对象的实例
        /// </summary>
        /// <param name="serviceProvider"></param>
        /// <param name="baseSubscribeTypeModel"></param>
        /// <returns></returns>
        private object GetObjInstance(IServiceProvider serviceProvider, BaseSubscribeTypeModel baseSubscribeTypeModel)
        {
            return serviceProvider.GetRequiredService(baseSubscribeTypeModel.ServiceType);
        }

        /// <summary>
        /// 构建参数
        /// </summary>
        /// <returns></returns>
        private List<ParameterEntity> BuildParameter(ParameterInfo[] parameterInfos, MessageModel messageModel)
        {
            if (parameterInfos == null)
            {
                return default;
            }
            var resultList = new List<ParameterEntity>();

            foreach (var item in parameterInfos)
            {
                //验证当前是否为来自消息头的
                if (item.GetCustomAttribute<HeaderAttribute>() != null)
                {
                    resultList.Add(new ParameterEntity
                    {
                        ParameterType = item.ParameterType,
                        Value = messageModel.Header
                    });
                }
                else
                {
                    resultList.Add(new ParameterEntity
                    {
                        ParameterType = item.ParameterType,
                        Value = messageModel.MessageContent?.ToDeserialized(item.ParameterType)
                    });
                }
            }
            return resultList;
        }

    }
}
